/** 
 *  @file
 *  @brief 静力分析测试带参模板
 *  @author  wanghuan
 *  @date    2024.06.24
 *  @version  v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once

#include "gtest/gtest.h"

#include "Utility/FileSystem/SGFileSystem.h"

#include "DataStructure/Input/Solver/Project.h"
#include "DBManager/Database/DatabaseFactory.h"
#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

#include "Import/ImportAPI/ImportAPI.h"
#include "Export/VTKExport/VTKExport.h"
#include "../StaticSolver.h"

using namespace SG::Utility::FileSystem;
using SG::DataStructure::Common::Status;
using SG::DataStructure::FEM::Project;
using namespace SG::DBManager;

extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;

struct TestModel
{
    std::string inputFile;
    std::string targetFile;
};

class StaticTest : public ::testing::TestWithParam<TestModel>
{
protected:
    void SetUp () override
    {
        modelPath = getTestDataPath ("SGFem/Task/Input/");
        resultFilePath = getTestDataPath ("SGFem/Task/");
    }

    void TearDown () override
    {
        DB_SERVICEFACTORY->ClearDatabase ();
    }
    std::string modelPath; ///< 输入模型文件路径
    std::string resultFilePath; ///< 期望结果（正确）文件路径
};

TEST_P (StaticTest, ComputeDisplacementAsExpect)
{
    TestModel para = GetParam ();
    Project project;
    project.m_modelFilePath = modelPath;
    project.m_modelFileName = para.inputFile;
    auto posi = para.inputFile.find('.');
    project.m_jobName = para.inputFile.substr(0, posi);

    DB_SERVICEFACTORY->ClearDatabase ();
    
    SG::Import::SGImporter importer (DB_SERVICEFACTORY);
    auto status = importer.Import (project.m_modelFilePath + project.m_modelFileName);

    ASSERT_EQ (status, Status::STATUS_Success);
    
    // 获取模型中所有的subCase
    auto subcaseIds = DB_SERVICEFACTORY->get<ISubcaseService> ()->GetAllSubcaseID ();

    StaticSolver solver;
    solver.Solve (DB_SERVICEFACTORY, project, subcaseIds);
    SG::Post::vtkOutput (DB_SERVICEFACTORY, project.m_workSpace + project.m_jobName + ".vtk");

    // Check
    auto fileTest = getFullPath (project.m_jobName + ".vtk");
    auto fileTarget = resultFilePath + para.targetFile;
    
    ASSERT_TRUE (compareVTK (fileTarget, fileTest));
};

/** 分析流程中各种约束实现的测试
 * 
 */
INSTANTIATE_TEST_CASE_P (ConstraintCmd, StaticTest, testing::Values(
    TestModel{"crod_forced_displacement_constraint.bdf", "crod_forced_displacement_constraint_Target.vtk"}, // 强制位移
    TestModel{"Grid_Ps_constraint_Cbar.bdf", "Grid_Ps_constraint_Cbar_Static_Target.vtk"}, // 节点具有PS约束
    TestModel{"spc1_thru_fake_point_cquad4.bdf", "spc1_thru_fake_point_cquad4_Static_Target.vtk"}, // 单点约束SPC1壳单元测试包含"THRU"，THRU的节点集合包含不存在的节点，引发warning，但是程序不应崩溃
    TestModel{"MPC_cbar_spc.bdf", "MPC_cbar_spc_Static_Target.vtk"} // MPC 多点约束处理
    ,TestModel{"CORD1C_OutputDispInLocal.bdf", "CORD1C_OutputDispInLocal_Static_Target.vtk"} // cbar单元节点位移输出坐标系比对
));

/** 集中力载荷计算测试 
 * 
*/
INSTANTIATE_TEST_CASE_P (NodalForce, StaticTest, testing::Values(
     TestModel{"Load_Force1_Apply_Point_CD.bdf", "Load_Force1_Apply_Point_CD_Static_Target.vtk"} // 两点定义力载荷方向
    //  ,TestModel{"PLOAD_chexa.bdf", "Load_Force1_Apply_Point_CD_Static_Target.vtk"} // 两点定义力载荷方向
));

/**
 * @brief    PLOAD1测试
 * 
 */
INSTANTIATE_TEST_CASE_P (PLoad1, StaticTest, testing::Values(
    TestModel{"Pload1_cbar_LE_FY_Distribution.bdf", "Pload1_cbar_LE_FY_Distribution_Static_Target.vtk"}
));

/** 杆单元测试
 * 
 */
INSTANTIATE_TEST_CASE_P (RodElement, StaticTest, testing::Values(
    TestModel{"CROD_Tension_CD.bdf",  "CROD_Tension_CD_Static_Target.vtk"} // 节点位移输出坐标系
    ,TestModel{"crod_NSM_tension_compression_GRAV.bdf", "crod_NSM_tension_compression_GRAV_Static_Target.vtk"} // 重力载荷+非结构质量
));

/** CBAR梁测试
 * 
 */
INSTANTIATE_TEST_CASE_P (BarElement, StaticTest, testing::Values(
    TestModel{"CBAR_PBAR_GOO_PIN_CP_CD_CORD2R.bdf",  "CBAR_PBAR_GOO_PIN_CP_CD_CORD2R_Static_Target.vtk"}// Bar单元节点具有位移输出坐标系
    ,TestModel{"PBARL_AllSectionPropCalc.bdf", "PBARL_AllSectionPropCalc_Static_Target.vtk"} // PBARL18种截面计算功能测试（ROD、TUBE、I、CHAN、T、BOX、BAR、CROSS、H、T1、I1、CHAN1、Z、CHAN2、T2、BOX1、HAT截面计算已通过；HEXA截面计算未通过）
    ,TestModel{"cbar_orientation_vector_float_Bar_Sec_spc.bdf", "cbar_orientation_vector_float_Bar_Sec_spc_Static_Target.vtk"}, // 导入模块能否正确识别CBAR单元的朝向矢量
    TestModel{"CBAR_Orientation_G0.bdf", "CBAR_Orientation_G0_Static_Target.vtk"} // 解析CBar词条，是否考虑定向节点
    ,TestModel{"CBAR_DirectionVecIsCORD1C.bdf", "CBAR_DirectionVecIsCORD1C_Static_Target.vtk"}// cbar单元朝向矢量在柱坐标系情况下输出位移验证
    ,TestModel{"CBAR_NodeDofRelease.bdf", "CBAR_NodeDofRelease_Static_Target.vtk"} // cbar单元节点自由度释放导入
));

/** 剪切单元测试
 * 
 */
INSTANTIATE_TEST_CASE_P (CShearElement, StaticTest, testing::Values(
    TestModel{"pshear_cbar_cquad4_spc.bdf", "pshear_cbar_cquad4_spc_Static_Target.vtk"} // 导入剪切单元属性
    ,TestModel{"cshear_grav.bdf", "cshear_grav_Target.vtk"} // 导入剪切单元属性
));

/** 质量单元测试
 * 
 */
// INSTANTIATE_TEST_CASE_P (CONM1Element, StaticTest, testing::Values(
//     TestModel{"conm1_pshear_cquad4_F1_F2_spc_grav.bdf", "conm1_pshear_cquad4_F1_F2_spc_grav_Static_Target.vtk"} // 导入质量单元属性
// ));

/** 壳单元测试
 * 
 */
INSTANTIATE_TEST_CASE_P (CQUAD4Element, StaticTest, testing::Values(
    TestModel{"Membrane_plate_patch_cquad4_spc.bdf", "Membrane_plate_patch_cquad4_spc_Static_Target.vtk"} // Cquad4单元，膜部分分片试验
    // ,TestModel{"cantilever_chanSection_cquad4.bdf", "cantilever_chanSection_cquad4_Static_Target.vtk"} // C字梁使用壳单元划分，测试Drill的性能
    // 指定剪切修正系数数值
    // 指定弯曲修正系数
    // 偏置 [除了位移外，应该考虑对单元内力进行测试].
    // ,TestModel{"cquad4_RefSurfaceOffset.bdf", "cquad4_RefSurfaceOffset_Static_Target.vtk"} // 四边形壳中面偏置测试


    // 变厚度
    // 节点相对厚度 TFlag
    // 复合材料（对称铺层）
    // 复合材料 （非对称铺层）拉弯耦合
    // PCOMP偏置
    // 单元坐标系 cid
    // 单元角度  
    // 四点不共面
    // 重力载荷
    // 面压力
));

/** 8节点6面体单元
 * 
 */
INSTANTIATE_TEST_CASE_P (Hexa8Element, StaticTest, testing::Values(
     TestModel{"Solid_patch_chexa8.bdf",  "Solid_patch_chexa8_Static_Target.vtk"} // 8节点6面体单元分片试验
     ,TestModel{"mat9_chexa8.bdf",  "mat9_chexa8_Static_Target.vtk"} // 材料采用三维各项异性材料MAT9，卡片填写完整，导入计算结果
     ,TestModel{"chexa8_grav.bdf",  "chexa8_grav_Static_Target.vtk"} // 8节点6面体单元，含重力载荷
));

/** 四节点实体单元
 * 
 */
INSTANTIATE_TEST_CASE_P (TetraElement, StaticTest, testing::Values(
     TestModel{"CTETRA4_1Ele_CD.bdf",  "CTETRA4_1Ele_CD_Static_Target.vtk"} // 四面体单元节点具有位移输出坐标系
));

/** 连接单元 
 * cweld单元， cfast单元
 */
INSTANTIATE_TEST_CASE_P (ConnectElement, StaticTest, testing::Values(
    TestModel{"Cweld_ELEMID_S2SSortTest.bdf",  "Cweld_ELEMID_S2SSortTest_Static_Target.vtk"}, 
    // TestModel{"Cweld_GaEqualGb.bdf", "Cweld_GaEqualGb_Static_Target.vtk"}, //L=0情况 /** linux 误差较大 */
    TestModel{"Cfast_CQUAD4Patch.bdf", "Cfast_CQUAD4Patch_Static_Target.vtk"},
    TestModel{"Cfast_CTRIA3Patch.bdf", "Cfast_CTRIA3Patch_Static_Target.vtk"} 
));


/** R单元测试
 * 
 */
INSTANTIATE_TEST_CASE_P (RigidElement, StaticTest, testing::Values(
    TestModel{"rbar_GBAllDOFConstraint.bdf",  "RBAR_GBAllDOFConstraint_Static_Target.vtk"}, // CNA = “123456” ， CMB = “123456”
    TestModel{"Import_RBAR_AllCNA_DefaultCM.bdf", "Import_RBAR_AllCNA_DefaultCM_Static_Target.vtk"}, // CNA = “123456”，CNB = CMA = CMB = “ ”
    TestModel{"Import_RBAR_AllCNB_DefaultCM.bdf", "Import_RBAR_AllCNB_DefaultCM_Static_Target.vtk"}, // CNB = “123456”，CNA = CMA = CMB = “ ”
    TestModel{"rbar_GBPartDOFConstraint.bdf", "RBAR_GBPartDOFConstraint_Static_Target.vtk"},         // CNA = “123456” ， CMB = “124”, CNB = CMA = " "
    TestModel{"RBAR_BNodeMaster_ANodeAllSlave.bdf", "RBAR_BNodeMaster_ANodeAllSlave_Static_Target.vtk"}, // CNB = “123456”，CMB = “123456”，CNA = CMA= “ ”
    TestModel{"RBAR1_ConstraintLessThan6.bdf", "RBAR1_ConstraintLessThan6_Static_Target.vtk"},           // 只约束GB节点的部分自由度，CB = “126”
    TestModel{"RBAR1_DefaultGB.bdf", "RBAR1_DefaultGB_Static_Target.vtk"},                              // CB = “ ”，测试程序能否为CB赋值为“123456”
    TestModel{"rbar1_slaveDOFEqual6Case.bdf", "RBAR1_SlaveDOFEqual6Case_Static_Target.vtk"},
    TestModel{"rbe2_slaveDOFEqual6Case.bdf",  "RBE2_slaveDOFEqual6Case_Static_Target.vtk"},
    TestModel{"RBE2_cbar_CPCoord.bdf",        "RBE2_cbar_CPCoord_Static_Target.vtk" }
    ,TestModel{"rbe3_weight_center_cbar.bdf", "rbe3_weight_center_cbar_Target.vtk"}
    ,TestModel{"rbe3_No_weight_center_cbar.bdf", "rbe3_No_weight_center_cbar_Static_Target.vtk"}
    ,TestModel{"rbe3_cbar_cbar_T1.bdf", "rbe3_cbar_cbar_T1_Static_Target.vtk"}
));


/** CELAS单元测试
 * 
 */
INSTANTIATE_TEST_CASE_P (CELASElement, StaticTest, testing::Values(
     TestModel{"CELAS1_TwoNodalDofs.bdf",  "CELAS1_TwoNodalDofs_Static_Target.vtk"},                    //Celas1两点测试
     TestModel{"oneCElas1_G2ConncetToGround.bdf",  "oneCElas1_G2ConncetToGround_Static_Target.vtk"},     //Celas1接地测试
     TestModel{"celas2.bdf",  "celas2_Static_Target.vtk"}                                               //celas2两点测试
));



/** CMASS单元测试
* 
*/
INSTANTIATE_TEST_CASE_P (CMASSElement, StaticTest, testing::Values(
     TestModel{"cmass2_2connnect_cquad4.bdf",  "cmass2_2connnect_cquad4_Static_Target.vtk"},    //CMASS2两点
     TestModel{"cmass2_2load_cquad4.bdf",  "cmass2_2load_cquad4_Static_Target.vtk"}             //CMASS2接地
));